package com.tinyproxy.local;

import com.tinyproxy.common.Kits;
import com.tinyproxy.local.socks.TinySocks;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.util.UUID;

public class AuthHandler extends ChannelInboundHandlerAdapter {

    public interface AuthEcho {

        void echo(ChannelHandlerContext ctx, boolean success, byte[] newToken) throws Exception;

    }

    private final byte[] staticToken;

    private final TinySocks socks;

    private byte[] newToken;

    private final AuthEcho fnEcho;

    public AuthHandler(byte[] staticToken, TinySocks socks, AuthEcho fnEcho) {
        this.staticToken = staticToken;
        this.socks = socks;
        this.fnEcho = fnEcho;
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        String parts = socks.host() + "\0" + socks.port() + "\0" + UUID.randomUUID() + "\0"
                + System.currentTimeMillis();
        byte[] finalData = Kits.asBytes(parts);
        byte[] sha = Kits.toSha256(finalData);// 原始数据SHA256
        Kits.encrypt(staticToken, finalData);// 原始数据加密

        ByteBuf buf = Unpooled.buffer();
        buf.writeBytes(sha);
        Kits.writeInt(buf, finalData.length);
        buf.writeBytes(finalData);
        ctx.writeAndFlush(buf);

        // 加密数据+静态令牌后做SHA256，生成新的令牌
        newToken = Kits.toSha256(finalData, staticToken);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        int v = Kits.readInt((ByteBuf) msg);
        fnEcho.echo(ctx, v > Kits.RESP_MID, newToken);
        ctx.pipeline().remove(this);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        fnEcho.echo(ctx, false, newToken);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        fnEcho.echo(ctx, false, newToken);
    }

}
